﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using CaiyinSoft.NetGather.Protocol;
using CaiyinSoft.NetGather.NetGatherLib;
using CaiyinSoft.NetGather.NetGatherUtility;
using CaiyinSoft.NetGather.NetGatherLib.Filter;
using CaiyinSoft.NetGather.NetGatherLib.Analyzer;
using CaiyinSoft.NetGather.NetGatherLib.Publisher;
using CaiyinSoft.NetGather.NetGatherLib.URLSource;
using CaiyinSoft.NetGather.NetGatherLib.Filter.Process;
using CaiyinSoft.NetGather.NetGatherLib.Filter.Special;
using CaiyinSoft.NetGather.NetGatherLib.Filter.Generate;


namespace CaiyinSoft.NetGather.NetGather
{
    public partial class FrmMain : Form
    {

        private TaskList _taskList = null;
        private string _taskPath = Path.Combine(GloalVariable.StartUpPath, "TaskList.lst");
        private TreeNode _taskZone = null;
        private bool _stopFlag = false;

        public TreeNode SelectedNode
        {
            get
            {
                return getSelectNode(); // trvTasks.SelectedNode;
            }
            set
            {
                setSelectNode(value);
            }
        }

        public FrmMain()
        {
            InitializeComponent();
            _taskZone = new TreeNode("任务区");
            _taskZone.ImageIndex = 0;
            _taskZone.SelectedImageIndex = 0;

        }

        private void loadTasks()
        {
            if (File.Exists(_taskPath))
                _taskList = TaskList.Read(_taskPath);
            else
                _taskList = new TaskList(_taskPath);

            refreshTasks();
        }

        private void refreshTasks()
        {
            _taskZone.Nodes.Clear();
            foreach (var item in _taskList.Tasks)
            {
                TreeNode node = _taskZone.Nodes.Add(item.TaskName);
                node.ImageIndex = 1;
                node.SelectedImageIndex = 1;
                node.Tag = item;
            }
            _taskZone.ExpandAll();
        }

        private void saveTasks()
        {
            TaskList.Save(_taskPath, this._taskList);
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            trvTasks.Nodes.Add(_taskZone);
            loadTasks();
        }

        private void tbNew_Click(object sender, EventArgs e)
        {
            FrmTaskEditer edit = new FrmTaskEditer();
            edit.TaskListItem = new TaskListItem();
            DialogResult res = edit.ShowDialog(); ;
            if (res != DialogResult.OK) return;

            this._taskList.AddItem(edit.TaskListItem);
            TreeNode node = _taskZone.Nodes.Add(edit.TaskListItem.TaskName);
            node.ImageIndex = 1;
            node.SelectedImageIndex = 1;
            node.Tag = edit.TaskListItem;

            saveTasks();
        }


        private void tbEdit_Click(object sender, EventArgs e)
        {
            TaskListItem item = trvTasks.SelectedNode.Tag as TaskListItem;
            if (item == null) return;

            FrmTaskEditer edit = new FrmTaskEditer();
            edit.TaskListItem = item;
            DialogResult res = edit.ShowDialog(); ;
            if (res != DialogResult.OK) return;

            trvTasks.SelectedNode.Text = edit.TaskListItem.TaskName;
            showTaskInfo(trvTasks.SelectedNode);

            saveTasks();

        }

        private void tbDel_Click(object sender, EventArgs e)
        {


            TaskListItem item = trvTasks.SelectedNode.Tag as TaskListItem;
            if (item == null) return;

            DialogResult res = MessageBox.Show(string.Format("确定删除任务:{0}", item.TaskName), Application.ProductName, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (res != DialogResult.OK) return;

            string filePath = item.GetFullPath();

            this._taskList.DelItem(item);

            trvTasks.SelectedNode.Remove();
            saveTasks();

            if (System.IO.File.Exists(filePath))
            {
                try
                {
                    System.IO.File.Delete(filePath);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void tbSave_Click(object sender, EventArgs e)
        {
            saveTasks(); // TaskList.Save(_taskPath, this._taskList);
        }

        private void tbRefresh_Click(object sender, EventArgs e)
        {
            refreshTasks();
        }

        private void tbImport_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Title = "导入文件";
            dialog.Filter = string.Format("任务文件|*{0}", Task.Extension);
            dialog.DefaultExt = Task.Extension;
            DialogResult res = dialog.ShowDialog();
            if (res != DialogResult.OK) return;

            Task task = null;
            try
            {
                task = Task.Read(dialog.FileName);
            }
            catch (FormatExpection ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            string taskID = Guid.NewGuid().ToString();
            string path = Path.Combine(GloalVariable.StartUpPath, string.Format(@"tasks\{0}{1}", taskID, Task.Extension));

            try
            {
                if (dialog.FileName.ToLower().CompareTo(path.ToLower()) != 0)
                    File.Copy(dialog.FileName, path, true);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            TaskListItem item = new TaskListItem();
            item.TaskID = taskID;
            item.TaskName = task.TaskName;

            this._taskList.AddItem(item);
            TreeNode node = _taskZone.Nodes.Add(item.TaskName);
            node.Tag = item;

            saveTasks();

        }

        private void trvTasks_AfterSelect(object sender, TreeViewEventArgs e)
        {
            try
            {
                showTaskInfo(e.Node);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

        }

        private void showTaskInfo(TreeNode treeNode)
        {
            TaskListItem item = treeNode.Tag as TaskListItem;
            lsvConverters.Items.Clear();
            if (item == null) return;

            Task task = Task.Read(item.GetFullPath());
            setTaskEvents(task);

            List<URLItem> URLItems = task.URLSource.GetURLCollection();

            if (URLItems == null) return;
            lsvConverters.Tag = URLItems;

            int j = 0;
            for (int i = 0; i < URLItems.Count; i++) // var urlitem in URLItems)
            {
                URLItem urlitem = URLItems[i];
                //if (urlitem.Status != URLItemStatus.NotRunning) continue;
                ListViewItem lvitem = lsvConverters.Items.Add(urlitem.URL.GetHashCode().ToString(), "", 0);
                lvitem.SubItems.Add(urlitem.URL);
                lvitem.Tag = urlitem;
                j++;
                if (j >= 100)
                {
                    break;
                }
            }
        }

        private void continueAddUriItems()
        {
            List<URLItem> URLItems = (List<URLItem>)lsvConverters.Tag;
            if (URLItems == null) return;
            if (URLItems.Count == lsvConverters.Items.Count) return;

            int itemCount = lsvConverters.Items.Count;
            int j = 0;
            for (int i = itemCount; i < URLItems.Count; i++)
            {
                var urlitem = URLItems[i];
                //if (urlitem.Status != URLItemStatus.NotRunning) continue;
                ListViewItem lvitem = lsvConverters.Items.Add(urlitem.URL.GetHashCode().ToString(), "", 0);
                lvitem.SubItems.Add(urlitem.URL);
                lvitem.Tag = urlitem;
                j++;
                if (j >= 100)
                {
                    break;
                }
            }
        }

        private void setTaskEvents(Task task)
        {
            task.BeforePageGatherHandler += new EventHandler<PageGatherEventAgr>(task_BeforePageGatherHandler);
            task.TaskRunStatusHandler += new EventHandler<RunStatusEventAgr>(task_TaskRunStatusHandler);
            task.TaskStartHandler += new EventHandler(task_TaskStartHandler);
            task.TaskStopHandler += new EventHandler(task_TaskStopHandler);
        }

        void task_TaskStopHandler(object sender, EventArgs e)
        {
            setToolButtonStatus(tbRun, true);
            setToolButtonStatus(tbRunSingle, true);
            setToolButtonStatus(tbRunAll, true);
            setToolButtonStatus(tbStop, false);
            showStatusText(string.Format("{0} 任务结束", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")));
        }

        void task_TaskStartHandler(object sender, EventArgs e)
        {
            setToolButtonStatus(tbRun, false);
            setToolButtonStatus(tbRunSingle, false);
            setToolButtonStatus(tbRunAll, false);
            setToolButtonStatus(tbStop, true);
            showStatusText(string.Format("{0} 任务开始", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")));

        }

        void task_TaskRunStatusHandler(object sender, RunStatusEventAgr e)
        {
            string status = "";
            switch (e.URLItem.Status)
            {
                case URLItemStatus.NotRunning:
                    status = "未运行";
                    break;
                case URLItemStatus.Running:
                    status = "开始下载";
                    break;
                case URLItemStatus.Publicing:
                    status = "开始发布";
                    break;
                case URLItemStatus.Finished:
                    status = "已完成";
                    break;
                case URLItemStatus.Error:
                    status = "出错了";
                    break;
                default:
                    status = "???";
                    break;

            }
            if (e.URLItem.Status == URLItemStatus.Running)
            {
                //showStatusClear();
            }

            showURLItemStatus(e.URLItem);
            showStatusText(status);
            //showStatusText(string.Format("{0} {1}", DateTime.Now.ToString("hh:mm:ss"), e.URLItem.URL));
        }

        void task_BeforePageGatherHandler(object sender, PageGatherEventAgr e)
        {
            showStatusText(string.Format("{0} {1}", DateTime.Now.ToString("hh:mm:ss"), e.URL));
            e.Cancel = _stopFlag;
        }

        private void tmExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }


        delegate void RunTasksHandler();
        private void tbRunSingle_Click(object sender, EventArgs e)
        {
            _stopFlag = false;
            tbRun.Enabled = false;
            tbRunSingle.Enabled = false;
            tbRunAll.Enabled = false;
            tbStop.Enabled = false;
            rtStatus.Clear();

            RunTasksHandler d = new RunTasksHandler(runSingleTasks);
            d.BeginInvoke(taskStop, null);
        }

        private void tbRunAll_Click(object sender, EventArgs e)
        {
            _stopFlag = false;
            tbRun.Enabled = false;
            tbRunSingle.Enabled = false;
            tbRunAll.Enabled = false;
            tbStop.Enabled = false;
            rtStatus.Clear();

            RunTasksHandler d = new RunTasksHandler(runAllTasks);
            d.BeginInvoke(taskStop, null);
        }


        void taskStop(IAsyncResult result)
        {
            setToolButtonStatus(tbRun, true);
            setToolButtonStatus(tbRunSingle, true);
            setToolButtonStatus(tbRunAll, true);
            setToolButtonStatus(tbStop, false);

            showStatusText(string.Format("{0} 任务结束", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")));

        }

        private void runSingleTasks()
        {
            TreeNode treeNode = SelectedNode;
            TaskListItem item = treeNode.Tag as TaskListItem;
            if (item == null) return;

            Task task = Task.Read(item.GetFullPath());
            setTaskEvents(task);
            task.Start();
        }

        private void runAllTasks()
        {
            for (int i = 0; i < _taskZone.Nodes.Count; i++)
            {
                TreeNode treeNode = _taskZone.Nodes[i];
                SelectedNode = treeNode;
                TaskListItem item = treeNode.Tag as TaskListItem;
                if (item == null) continue;

                Task task = Task.Read(item.GetFullPath());
                setTaskEvents(task);
                task.Start();
            }
        }

        private void tbStop_Click(object sender, EventArgs e)
        {
            _stopFlag = true;
            tbStop.Enabled = false;
        }

        delegate void SetSelectNodeHandler(TreeNode node);
        private void setSelectNode(TreeNode node)
        {
            if (this.InvokeRequired == false)
            {
                trvTasks.SelectedNode = node;
                //trvTasks.SelectedNode.ImageIndex = 1;
            }
            else
            {
                SetSelectNodeHandler d = new SetSelectNodeHandler(setSelectNode);
                this.Invoke(d, new object[] { node });
            }
        }

        delegate TreeNode GetSelectNodeHandler();
        private TreeNode getSelectNode()
        {
            if (this.InvokeRequired == false)
            {
                return trvTasks.SelectedNode;
            }
            else
            {
                GetSelectNodeHandler d = new GetSelectNodeHandler(getSelectNode);
                return (TreeNode)this.Invoke(d);
            }

        }

        delegate void SetToolButtonStatusHandler(ToolStripItem bt, bool enabled);
        private void setToolButtonStatus(ToolStripItem bt, bool enabled)
        {
            if (this.InvokeRequired == false)
            {
                bt.Enabled = enabled;
            }
            else
            {
                SetToolButtonStatusHandler d = new SetToolButtonStatusHandler(setToolButtonStatus);
                this.Invoke(d, new object[] { bt, enabled });
            }
        }

        delegate void ShowStatusTextHandler(string status);
        private void showStatusText(string status)
        {
            if (this.InvokeRequired == false)
            {
                rtStatus.AppendText(status);
                rtStatus.AppendText(Environment.NewLine);
            }
            else
            {
                ShowStatusTextHandler d = new ShowStatusTextHandler(showStatusText);
                this.Invoke(d, new object[] { status });
            }
        }


        delegate void ShowStatusClearHandler();
        private void showStatusClear()
        {
            if (this.InvokeRequired == false)
            {
                rtStatus.Clear();
            }
            else
            {
                ShowStatusClearHandler d = new ShowStatusClearHandler(showStatusClear);
                this.Invoke(d, new object[] { });
            }
        }
        //private void RunTask(Task task)
        //{
        //    task.Start();
        //}

        //private void StopTask(Task task)
        //{
        //    task.Stop();
        //}

        delegate void ShowURLItemStatus(URLItem item);
        private void showURLItemStatus(URLItem item)
        {
            if (this.InvokeRequired == false)
            {
                ListViewItem[] lvItems = lsvConverters.Items.Find(item.URL.GetHashCode().ToString(), false);

                if (lvItems.Length > 0)
                {
                    ListViewItem lvItem = lvItems[0];
                    lsvConverters.FocusedItem = lvItem;
                    lsvConverters.EnsureVisible(lvItem.Index);
                    if (lvItem.Index + 1 >= lsvConverters.Items.Count)
                        continueAddUriItems();
                    //lvItems[0].Position
                    switch (item.Status)
                    {
                        case URLItemStatus.NotRunning:
                            lvItems[0].ImageIndex = 0;
                            break;
                        case URLItemStatus.Running:
                            lvItems[0].ImageIndex = 1;
                            break;
                        case URLItemStatus.Finished:
                            lvItems[0].ImageIndex = 3;
                            break;
                        case URLItemStatus.Error:
                            lvItems[0].ImageIndex = 2;
                            break;
                        default:
                            lvItems[0].ImageIndex = 0;
                            break;
                    }
                }
                else
                {
                    continueAddUriItems();
                }
            }
            else
            {
                ShowURLItemStatus d = new ShowURLItemStatus(showURLItemStatus);
                this.Invoke(d, new object[] { item });
            }
        }

        private void lsvConverters_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ListViewHitTestInfo testInfo = lsvConverters.HitTest(e.X, e.Y);
            if (testInfo == null || testInfo.Item == null) return;

            string url = testInfo.Item.SubItems[1].Text;
            System.Diagnostics.Process.Start(url);

        }

        private void tmCopy_Click(object sender, EventArgs e)
        {
            TaskListItem item = trvTasks.SelectedNode.Tag as TaskListItem;
            if (item == null) return;
            string newName = string.Empty;
            bool checkBoxChecked = false;
            bool taskExists = false;
            do
            {
                newName = Utility.OpenInputMessageBox("输入新的任务名称", item.TaskName, "覆盖同名任务", out checkBoxChecked);
                if (newName == string.Empty) return;

                var t = this._taskList.Tasks.Find(m => m.TaskName == newName);
                if (t != null)
                {
                    if (!checkBoxChecked)
                    {
                        MessageBox.Show(string.Format("{0} 的任务已经存在", newName), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else
                    {
                        taskExists = true;
                        break;
                    }
                }
                else
                {
                    break;
                }
            } while (true);

            string oldPath = item.GetFullPath();
            string newPath = Path.Combine(GloalVariable.StartUpPath, string.Format(@"tasks\{0}{1}", newName, Task.Extension));

            if (System.IO.File.Exists(newPath))
            {
                if (checkBoxChecked)
                {
                    System.IO.File.Delete(newPath);
                }
                else
                {
                    MessageBox.Show("文件名已存在,不能继续!", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
            }

            System.IO.File.Copy(oldPath, newPath, false);


            TaskListItem newItem = null;
            if (taskExists)
            {
                newItem = this._taskList.Tasks.Find(m => m.TaskName == newName);
            }
            else
            {
                newItem = new TaskListItem();
                newItem.TaskName = newName;
                newItem.TaskID = Guid.NewGuid().ToString();
                this._taskList.AddItem(newItem);
                TreeNode node = _taskZone.Nodes.Add(newItem.TaskName);
                node.ImageIndex = 1;
                node.SelectedImageIndex = 1;
                node.Tag = newItem;
                saveTasks();
            }

            try
            {
                Task task = Task.Read(newItem.GetFullPath());
                task.TaskID = newItem.TaskID;
                task.TaskName = newName;
                CaiyinSoft.NetGather.NetGatherLib.Task.Save(newItem.GetFullPath(), task, string.IsNullOrEmpty(newItem.TaskID));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }

        private void trvTasks_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right) return;
            TreeViewHitTestInfo test= trvTasks.HitTest(e.X, e.Y);
            if (test == null || test.Node == null) return;

            contextMenuStrip1.Show(trvTasks, new Point(e.X, e.Y));

            TaskListItem item = test.Node.Tag as TaskListItem;
            if (item != null)
            {
                trvTasks.SelectedNode = test.Node;
            }

        }



    }
}
